package com.kinyx.framework.reflect;

import java.lang.reflect.Field;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import com.kinyx.framework.bean.KeyValues;

import lombok.Getter;
import lombok.Setter;

public class KFieldUtils_Tester_getFieldList_0_getField {

	@Getter
	@Setter
	public static class Super {

		// normal
		private String private_normal = "foo";
		protected String protected_normal = "foo";
		String package_normal = "foo";
		public String public_normal = "foo";

		// static
		@SuppressWarnings("unused")
		private static String private_static = "foo";
		protected static String protected_static = "foo";
		static String package_static = "foo";
		public static String public_static = "foo";

		// final
		private final String private_final = "foo";
		protected final String protected_final = "foo";
		final String package_final = "foo";
		public final String public_final = "foo";

		// static final
		@SuppressWarnings("unused")
		private static final String private_static_final = "foo";
		protected static final String protected_static_final = "foo";
		static final String package_static_final = "foo";
		public static final String public_static_final = "foo";

	}

	@Getter
	@Setter
	public static class Sub extends Super {

		// normal
		private String private_normal = "bar";
		protected String protected_normal = "bar";
		String package_normal = "bar";
		public String public_normal = "bar";

		// static
		@SuppressWarnings("unused")
		private static String private_static = "bar";
		protected static String protected_static = "bar";
		static String package_static = "bar";
		public static String public_static = "bar";

		// final
		private final String private_final = "bar";
		protected final String protected_final = "bar";
		final String package_final = "bar";
		public final String public_final = "bar";

		// static final
		@SuppressWarnings("unused")
		private static final String private_static_final = "bar";
		protected static final String protected_static_final = "bar";
		static final String package_static_final = "bar";
		public static final String public_static_final = "bar";

	}

	private String kv(final Field field, final Object obj) {
		if (!field.isAccessible()) {
			field.setAccessible(true);
		}
		Object value = null;
		try {
			value = field.get(obj);
		} catch (final IllegalArgumentException e) {
			e.printStackTrace();
		} catch (final IllegalAccessException e) {
			e.printStackTrace();
		}
		return String.format("%s=%s", field.getName(), value);
	}
	private String kvs(final List<Field> list, final Object obj) {
		final KeyValues kv = KeyValues.of();
		list.forEach(field -> { kv.add(null, this.kv(field, obj)); });
		return "," + kv.get(null, null, null);
	}

	@Test
	public void testTypeTT() {
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_normal", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_normal", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_normal", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_normal", true, true));

		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_static", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_static", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_static", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_static", true, true));

		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_final", true, true));

		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_static_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_static_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_static_final", true, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_static_final", true, true));
	}

	@Test
	public void testTypeFT() {
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_normal", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_normal", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_normal", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_normal", false, true));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_static", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_static", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_static", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_static", false, true));

		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_final", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_final", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_final", false, true));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_final", false, true));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_static_final", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_static_final", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_static_final", false, true));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_static_final", false, true));
	}

	@Test
	public void testTypeTF() {
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_normal", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_normal", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_normal", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_normal", true, false));

		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_static", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_static", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_static", true, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_static", true, false));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_final", true, false));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_static_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_static_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_static_final", true, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_static_final", true, false));
	}

	@Test
	public void testTypeFF() {
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "private_normal", false, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "protected_normal", false, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "package_normal", false, false));
		Assert.assertNotNull(KFieldUtils.getField(Super.class, "public_normal", false, false));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_static", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_static", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_static", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_static", false, false));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_final", false, false));

		Assert.assertNull(KFieldUtils.getField(Super.class, "private_static_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "protected_static_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "package_static_final", false, false));
		Assert.assertNull(KFieldUtils.getField(Super.class, "public_static_final", false, false));
	}

	@Test
	public void test0() {
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "private_normal", true, true), new Super()), "private_normal=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "protected_normal", true, true), new Super()), "protected_normal=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "package_normal", true, true), new Super()), "package_normal=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "public_normal", true, true), new Super()), "public_normal=foo");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "private_static", true, true), new Super()), "private_static=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "protected_static", true, true), new Super()), "protected_static=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "package_static", true, true), new Super()), "package_static=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "public_static", true, true), new Super()), "public_static=foo");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "private_final", true, true), new Super()), "private_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "protected_final", true, true), new Super()), "protected_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "package_final", true, true), new Super()), "package_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "public_final", true, true), new Super()), "public_final=foo");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "private_static_final", true, true), new Super()), "private_static_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "protected_static_final", true, true), new Super()), "protected_static_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "package_static_final", true, true), new Super()), "package_static_final=foo");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Super.class, "public_static_final", true, true), new Super()), "public_static_final=foo");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "private_normal", true, true), new Sub()), "private_normal=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "protected_normal", true, true), new Sub()), "protected_normal=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "package_normal", true, true), new Sub()), "package_normal=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "public_normal", true, true), new Sub()), "public_normal=bar");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "private_static", true, true), new Sub()), "private_static=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "protected_static", true, true), new Sub()), "protected_static=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "package_static", true, true), new Sub()), "package_static=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "public_static", true, true), new Sub()), "public_static=bar");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "private_final", true, true), new Sub()), "private_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "protected_final", true, true), new Sub()), "protected_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "package_final", true, true), new Sub()), "package_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "public_final", true, true), new Sub()), "public_final=bar");

		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "private_static_final", true, true), new Sub()), "private_static_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "protected_static_final", true, true), new Sub()), "protected_static_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "package_static_final", true, true), new Sub()), "package_static_final=bar");
		Assert.assertEquals(this.kv(KFieldUtils.getField(Sub.class, "public_static_final", true, true), new Sub()), "public_static_final=bar");
	}

	@Test
	public void test1() {
		final Object obj = new Super();
		// ==== 去重 ==== //
		// （去重）（父类）（不排除字段）（static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, true, true, true), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//

				+ ",private_static_final=foo"//
				+ ",protected_static_final=foo"//
				+ ",package_static_final=foo"//
				+ ",public_static_final=foo"//
		);
		// （去重）（父类）（不排除字段）（static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, true, true, false), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//
		);
		// （去重）（父类）（不排除字段）（非static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, true, false, true), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//
		);
		// （去重）（父类）（不排除字段）（非static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, true, false, false), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//
		);

		// ==== 不去重 ==== //
		// （不去重）（父类）（不排除字段）（static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, false, true, true), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//

				+ ",private_static_final=foo"//
				+ ",protected_static_final=foo"//
				+ ",package_static_final=foo"//
				+ ",public_static_final=foo"//
		);

		// （不去重）（父类）（不排除字段）（static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, false, true, false), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//
		);
		// （不去重）（父类）（不排除字段）（非static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, false, false, true), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//
		);
		// （不去重）（父类）（不排除字段）（非static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, false, false, false), obj), ""//
				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//
		);
	}

	@Test
	public void test2() {
		final Object obj = new Sub();
		// ==== 去重 ==== //
		// （去重）（子类）（不排除字段）（static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, true, true, true), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_static=bar"//
				+ ",protected_static=bar"//
				+ ",package_static=bar"//
				+ ",public_static=bar"//

				+ ",private_final=bar"//
				+ ",protected_final=bar"//
				+ ",package_final=bar"//
				+ ",public_final=bar"//

				+ ",private_static_final=bar"//
				+ ",protected_static_final=bar"//
				+ ",package_static_final=bar"//
				+ ",public_static_final=bar"//
		);
		// （去重）（子类）（不排除字段）（static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, true, true, false), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_static=bar"//
				+ ",protected_static=bar"//
				+ ",package_static=bar"//
				+ ",public_static=bar"//
		);
		// （去重）（子类）（不排除字段）（非static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, true, false, true), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_final=bar"//
				+ ",protected_final=bar"//
				+ ",package_final=bar"//
				+ ",public_final=bar"//
		);
		// （去重）（子类）（不排除字段）（非static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, true, false, false), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//
		);

		// ==== 不去重 ==== //
		// （不去重）（子类）（不排除字段）（static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, false, true, true), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_static=bar"//
				+ ",protected_static=bar"//
				+ ",package_static=bar"//
				+ ",public_static=bar"//

				+ ",private_final=bar"//
				+ ",protected_final=bar"//
				+ ",package_final=bar"//
				+ ",public_final=bar"//

				+ ",private_static_final=bar"//
				+ ",protected_static_final=bar"//
				+ ",package_static_final=bar"//
				+ ",public_static_final=bar"//

				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//

				+ ",private_static_final=foo"//
				+ ",protected_static_final=foo"//
				+ ",package_static_final=foo"//
				+ ",public_static_final=foo"//
		);

		// （不去重）（子类）（不排除字段）（static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, false, true, false), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_static=bar"//
				+ ",protected_static=bar"//
				+ ",package_static=bar"//
				+ ",public_static=bar"//

				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_static=foo"//
				+ ",protected_static=foo"//
				+ ",package_static=foo"//
				+ ",public_static=foo"//
		);
		// （不去重）（子类）（不排除字段）（非static）（final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, false, false, true), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_final=bar"//
				+ ",protected_final=bar"//
				+ ",package_final=bar"//
				+ ",public_final=bar"//

				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

				+ ",private_final=foo"//
				+ ",protected_final=foo"//
				+ ",package_final=foo"//
				+ ",public_final=foo"//
		);
		// （不去重）（子类）（不排除字段）（非static）（非final）
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, false, false, false), obj), ""//
				+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//
		);
	}

	// 排除字段
	@Test
	public void test3() {
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, true, false, false, "private_normal"), new Super()), ""//
				//+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//
		);
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Super.class, false, false, false, "private_normal"), new Super()), ""//
				//+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//
		);

		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, true, false, false, "private_normal"), new Sub()), ""//
				//+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//
		);
		Assert.assertEquals(this.kvs(KFieldUtils.getFieldList(Sub.class, false, false, false, "private_normal"), new Sub()), ""//
				//+ ",private_normal=bar"//
				+ ",protected_normal=bar"//
				+ ",package_normal=bar"//
				+ ",public_normal=bar"//

				//+ ",private_normal=foo"//
				+ ",protected_normal=foo"//
				+ ",package_normal=foo"//
				+ ",public_normal=foo"//

		);
	}

}
